<template>
  <div class="app-container">
    <el-card style="margin: 10px">
      <div v-if="showSearch" slot="header" class="clearfix">
        <!--头部工具过滤-->
        <el-input v-model="listQuery.name" size="mini" maxlength="255" clearable style="width: 200px;margin-right: 5px;" placeholder="请输入角色名称" />
        <el-button type="success" size="mini" icon="el-icon-search" @click="handleFilter">搜索</el-button>
        <el-button type="warning" size="mini" icon="el-icon-refresh-left" @click="resetForm">重置</el-button>
      </div>
      <div class="opts">
        <!--左侧-->
        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleCreate">添加</el-button>
        <el-button type="success" :disabled="hasEdiObj" icon="el-icon-edit" size="mini" @click="handleUpdate(selectionChange[0])">修改
        </el-button>
        <el-button type="danger" :disabled="hasDelObj" icon="el-icon-delete" size="mini" @click="handleDelete">删除
        </el-button>
        <!--右侧-->
        <right-toolbar :show-search.sync="showSearch" :columns="columns" @queryTable="resetForm" />
      </div>
      <el-row :gutter="10">
        <el-col :span="18">
          <!--表格数据-->
          <el-table
            v-loading="loading"
            :data="tableData"
            style="width: 100%;"
            size="mini"
            element-loading-text="正在努力加载中..."
            :highlight-current-row="true"
            border
            fit
            @selection-change="handleSelectionChange"
            @row-click="rowClick"
          >
            <el-table-column type="selection" width="55" />
            <el-table-column v-if="columns[0].visible" prop="name" width="250px" label="角色名称" />
            <el-table-column v-if="columns[1].visible" prop="dataScope" width="100px" label="数据范围">
              <template slot-scope="scope">
                {{
                  scope.row.dataScope === 0 ? '全部' : scope.row.dataScope === 1 ? '自定义' : scope.row.dataScope === 2 ? '本部门' : scope.row.dataScope === 3 ? '本部门及下属' : scope.row.dataScope
                }}
              </template>
            </el-table-column>
            <el-table-column v-if="columns[2].visible" prop="level" width="100px" label="角色级别" />
            <!--            <el-table-column v-if="columns[3].visible" prop="state" label="状态" />-->
            <el-table-column v-if="columns[3].visible" prop="description" label="描述" />
            <el-table-column v-if="columns[4].visible" prop="createBy" width="100px" label="创建人">
              <template scope="scope">
                {{ scope.row.createdUser ? scope.row.createdUser.name : '' }}
              </template>
            </el-table-column>
            <el-table-column v-if="columns[5].visible" prop="createTime" width="150px" label="创建时间" />
            <el-table-column align="center" width="130px" label="操作">
              <template slot-scope="scope">
                <el-popconfirm title="您确定要删除吗？" style="margin-right: 5px" @confirm="deleteByIds([scope.row.id])">
                  <el-button slot="reference" type="danger" icon="el-icon-delete" size="mini" />
                </el-popconfirm>
                <el-button type="primary" icon="el-icon-edit" size="mini" @click="handleUpdate(scope.row)" />
              </template>
            </el-table-column>
          </el-table>
          <!--分页-->
          <pagination v-show="total>0" :total="total" :page.sync="page.pageNum" :limit.sync="page.pageSize" @pagination="queryAll" />
        </el-col>
        <el-col :span="6">
          <el-tabs type="border-card">
            <el-tab-pane label="菜单">
              <el-input v-model="menuName2" size="mini" clearable prefix-icon="el-icon-search" style="width: 275px;margin-right: 5px;" placeholder="输入菜单名称搜索" />
              <el-button size="mini" icon="el-icon-check" type="primary" @click="updateAuthMenuById">保存</el-button>
              <el-tree ref="menuTree" class="filter-tree" :data="menuTree" :filter-node-method="filterNode" show-checkbox node-key="id" :check-strictly="true" accordion highlight-current :props="defaultProps">
                <span slot-scope="{ node, data }" class="custom-tree-node">
                  <span>
                    <svg-icon v-if="data.icon" style="width: 20px;height: 20px;margin-right: 10px;" :icon-class="data.icon" class-name="disabled" />
                    <span v-if="data.type===0" style="color: #08adee">目录</span>
                    <span v-if="data.type===1" style="color: #08ea2d">菜单</span>
                    <span v-if="data.type===2" style="color: #f1e60c">按钮</span>
                    {{ data.name }}
                  </span>
                </span>
              </el-tree>
            </el-tab-pane>
            <el-tab-pane label="用户">
              <!--左侧-->
              <div class="opts">
                <Treeselect
                  :normalizer="normalizer"
                  :append-to-body="true"
                  :disable-branch-nodes="true"
                  z-index="9999"
                  search-nested
                  :show-count="true"
                  :options="deptTree"
                  placeholder="选择授权人员"
                  no-children-text="当前部门下无人员"
                  no-results-text="查无此人员"
                />
                <el-button type="primary" icon="el-icon-plus" size="mini" style="margin-left: 5px;" @click="handleCreate">添加</el-button>
              </div>
              <!--表格数据-->
              <el-table
                v-loading="userLoading"
                :data="userTableData"
                style="width: 100%;"
                size="mini"
                element-loading-text="正在努力加载中..."
                highlight-current-row
                border
                fit
              >
                <el-table-column prop="username" label="用户名" />
                <el-table-column prop="name" label="用户昵称" />
                <el-table-column align="center" width="70px" label="操作">
                  <template slot-scope="scope">
                    <el-popconfirm title="您确定要删除吗？" style="margin-right: 5px" @confirm="deleteByIds([scope.row.id])">
                      <el-button slot="reference" type="danger" icon="el-icon-delete" size="mini" />
                    </el-popconfirm>
                  </template>
                </el-table-column>
              </el-table>
            </el-tab-pane>
          </el-tabs>
        </el-col>
      </el-row>

    </el-card>
    <!--对话框-->
    <el-dialog :title="title" :visible.sync="dialogVisible" width="40%" @open="openDialog">
      <el-row :gutter="15">
        <el-form ref="formData" :model="formData" :rules="rules" size="mini" label-width="100px">
          <el-col :span="24">
            <el-form-item label="角色名称:" prop="name">
              <el-input v-model="formData.name" placeholder="请输入角色名称" maxlength="255" show-word-limit clearable :style="{width: '100%'}" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="数据范围:" prop="dataScope">
              <el-select v-model="formData.dataScope" :style="{width: '100%'}" placeholder="请选择">
                <el-option
                  v-for="item in dataScopeList"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="角色级别:" prop="level">
              <el-input-number v-model="formData.level" placeholder="排序" :min="0" :max="9999" :step="1" :style="{width: '100%'}" controls-position="right" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="描述:" prop="description">
              <el-input
                v-model="formData.description"
                type="textarea"
                :rows="3"
                maxlength="255"
                show-word-limit
                placeholder="请输入描述"
              />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="菜单权限:" prop="menuIds">
              <el-card shadow="never">
                <div slot="header" class="clearfix">
                  <el-input v-model="menuName" clearable prefix-icon="el-icon-search" placeholder="输入菜单名称搜索" />
                </div>
                <el-tree ref="tree" class="filter-tree" :data="menuTree" :filter-node-method="filterNode" show-checkbox node-key="id" :check-strictly="true" accordion highlight-current :props="defaultProps">
                  <span slot-scope="{ node, data }" class="custom-tree-node">
                    <span>
                      <svg-icon v-if="data.icon" style="width: 20px;height: 20px;margin-right: 10px;" :icon-class="data.icon" class-name="disabled" />
                      <span v-if="data.type===0" style="color: #08adee">目录</span>
                      <span v-if="data.type===1" style="color: #08ea2d">菜单</span>
                      <span v-if="data.type===2" style="color: #f1e60c">按钮</span>
                      {{ data.name }}
                    </span>
                  </span>
                </el-tree>
              </el-card>
            </el-form-item>
          </el-col>
        </el-form>
      </el-row>
      <div slot="footer" class="dialog-footer">
        <el-button size="mini" @click="dialogVisible = false">
          取消
        </el-button>
        <el-button type="primary" size="mini" @click="title==='添加'?create():updateById()">
          提交
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { Notification } from 'element-ui'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { deleteByIds, findAll, updateById, create, findUserByRoleId } from '@/api/role'
import { duTree } from '@/api/dept'
import { tree as menuTree } from '@/api/menu'
import Pagination from '@/components/Pagination'
import RightToolbar from '@/components/RightToolbar'

export default {
  name: 'Role',
  components: { Pagination, RightToolbar, Treeselect },
  data() {
    return {
      menuName: '',
      menuName2: '',
      dialogVisible: false,
      title: '添加',
      showSearch: true,
      normalizer(node) {
        return {
          id: node.id,
          label: node.name,
          children: node.children
        }
      },
      listQuery: {
        name: undefined
      },
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      rules: {
        name: [{ required: true, message: '请输入部门名称', trigger: 'blur' }],
        dataScope: [{ required: true, message: '请选择数据范围', trigger: 'change' }]
      },
      dataScopeList: [
        { value: 0, label: '全部' },
        { value: 1, label: '自定义' },
        { value: 2, label: '本部门' },
        { value: 3, label: '本部门及下属' },
        { value: 4, label: '本人' }
      ],
      selectionChange: [],
      hasDelObj: true,
      hasEdiObj: true,
      columns: [
        { key: 0, label: `角色名称`, visible: true },
        { key: 1, label: `数据范围`, visible: true },
        { key: 2, label: `角色级别`, visible: true },
        { key: 3, label: `描述`, visible: true },
        { key: 4, label: `创建人`, visible: true },
        { key: 5, label: `创建时间`, visible: true }
      ],
      menuTree: [],
      deptTree: [],
      total: 0,
      ids: [],
      page: {
        pageNum: 1,
        pageSize: 10,
        sort: '+create_time'
      },
      tableData: [],
      userLoading: false,
      userTableData: [],
      loading: false,
      formData: {
        id: undefined,
        name: '',
        level: 0,
        dataScope: undefined,
        description: '',
        menus: [],
        menuIds: []
      }
    }
  },
  watch: {
    menuName(val) {
      this.$refs.tree.filter(val)
    },
    menuName2(val) {
      this.$refs.menuTree.filter(val)
    }
  },
  created() {
    this.queryAll()
    menuTree().then(res => {
      this.menuTree = res
    })
    duTree().then(res => {
      this.deptTree = res
    })
  },
  methods: {
    // 过滤菜单
    filterNode(value, data) {
      if (!value) return true
      return data.name.indexOf(value) !== -1
    },
    // 搜索
    handleFilter() {
      this.listQuery.pageNum = 1
      this.queryAll()
    },
    // 重置
    resetForm() {
      this.listQuery = { name: undefined }
      this.handleFilter()
    },
    // 打开添加/修改对话框
    openDialog() {
      this.$nextTick(() => {
        this.$refs.tree.setCheckedKeys(this.formData.menuIds)
      })
    },
    // 打开添加对话框
    handleCreate() {
      this.formData = {
        id: undefined,
        name: '',
        level: 0,
        dataScope: undefined,
        description: '',
        menuIds: []
      }
      this.title = '添加'
      this.dialogVisible = true
      this.$nextTick(() => {
        this.$refs['formData'].clearValidate()
      })
    },
    // 打开修改对话框
    handleUpdate(row) {
      this.formData = Object.assign({}, row) // copy obj
      this.title = '修改'
      this.dialogVisible = true
      this.$nextTick(() => {
        this.$refs['formData'].clearValidate()
      })
    },
    // 点击删除按钮
    handleDelete() {
      if (this.ids.length === 0) {
        Notification.warning('请选择要删除的菜单')
        return
      }
      this.$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.deleteByIds(this.ids)
      })
    },
    // 选中行
    rowClick(row, column, event) {
      this.formData = row
      this.$refs.menuTree.setCheckedKeys(this.formData.menuIds)
      this.userLoading = true
      findUserByRoleId(row.id).then(res => {
        this.userTableData = res
        this.userLoading = false
      })
    },
    // 选中
    handleSelectionChange(val) {
      this.selectionChange = val
      this.ids.length = 0
      const _this = this
      if (val.length > 0) {
        this.hasEdiObj = val.length !== 1
        this.hasDelObj = false
      } else {
        this.hasDelObj = true
        this.hasEdiObj = true
      }
      val.forEach((element) => {
        _this.ids.push(element.id)
      })
    },
    // 查询所有
    queryAll() {
      this.loading = true
      this.tableData = []
      findAll(this.page, this.listQuery).then(res => {
        this.tableData = res.rows
        this.total = res.total
        this.tableData.forEach(item => {
          item.menuIds = []
          item.menus.map((obj, index) => {
            item.menuIds.push(obj.id)
          })
        })
        setTimeout(() => {
          this.loading = false
        }, 500)
      }).catch(() => {
        this.loading = false
      })
    },
    // 更新
    updateById() {
      this.$refs['formData'].validate((valid) => {
        if (!valid) return
        this.formData.menus = []
        this.formData.menuIds = this.$refs.tree.getCheckedKeys()
        this.formData.menuIds.map((obj, index) => {
          this.formData.menus.push({ id: obj })
        })
        updateById(this.formData).then(res => {
          this.dialogVisible = false
          Notification.success(res)
          this.handleFilter()
        })
      })
    },
    // 保存角色授权菜单
    updateAuthMenuById() {
      this.formData.menus = []
      this.formData.menuIds = this.$refs.menuTree.getCheckedKeys()
      this.formData.menuIds.map((obj, index) => { this.formData.menus.push({ id: obj }) })
      updateById(this.formData).then(res => { Notification.success(res) })
    },
    // 创建
    create() {
      this.$refs['formData'].validate((valid) => {
        if (!valid) return
        this.formData.menus = []
        this.formData.menuIds = this.$refs.tree.getCheckedKeys()
        this.formData.menuIds.map((obj, index) => {
          this.formData.menus.push({ id: obj })
        })
        create(this.formData).then(res => {
          this.dialogVisible = false
          Notification.success(res)
          this.handleFilter()
        })
      })
    },
    // 删除
    deleteByIds(ids) {
      if (ids.length > 0) {
        deleteByIds(ids).then(res => {
          Notification.success(res)
          this.handleFilter()
        })
      }
    }
  }
}
</script>

<style scoped>
.opts {
  padding: 4px 0;
  display: -webkit-flex;
  display: flex;
  align-items: center;
}

.opts .opts-right {
  margin-left: auto;
}
</style>
